Skip to content

fix(gates): give review-gate the same report rows the guard and the queue read - #2875

Open
HugoXK wants to merge 1 commit into
ThinkFlowLab:mainfrom
HugoXK:dev/5-review-gate-rows
Open

HugoXK wants to merge 1 commit into
ThinkFlowLab:mainfrom
HugoXK:dev/5-review-gate-rows

Conversation

@HugoXK

@HugoXK HugoXK commented Nov 11, 2026 •

Copy link
Copy Markdown
Contributor

fix(gates): give review-gate the same report rows the guard and the queue read

.github/scripts/review-gate.mjs built its reports rows in a third copy of a
shape that enqueue-guard.mjs:67 and merge-gate.mjs:224 had already been
fixed in (#2092, #2120). This copy drifted, and the report-only gate read a
different pull request than the queue gate does:

The effect: this report could answer PASS at a tip while the queue refused the
same tip for a standing request. The rows are now built once, by an exported
reportsFrom, so the drift is visible to a test instead of only to a diff.

What changed

  • .github/scripts/review-gate.mjs — reportsFrom({ comments, reviews, reviewComments }) builds all three faces (comment, review with state, and
    kind: 'review-comment' for a diff-line comment whose body is not blank);
    main() uses it and passes only the conclusion faces to decide.
  • The predicate isConclusionSource moved here from enqueue-rules.mjs, which
    re-exports it, so the guard and merge-gate.mjs keep their import. It is one
    definition, not a second copy: importing it the other way would have made an
    import cycle (enqueue-rules.mjs already imports parseReport from this
    file), and gate code should not have one.
  • .github/scripts/review-gate.test.mjs — four tests on GitHub-API-shaped
    fixtures.

The three row builders stay in three places on purpose: collapsing them is a
separate change with its own equivalence test ("same fixture, three readers,
byte-identical output"), and merging it here would hide the drift instead of
pinning it.

Red first, then green

  1. New tests against the base review-gate.mjs:
    SyntaxError: The requested module './review-gate.mjs' does not provide an export named 'isConclusionSource' → # tests 1 / # pass 0 / # fail 1,
    twice.
  2. The fixed builder mutated back to the base shape (no id, no state, empty
    reviews filtered out, no review-comment rows — behaviour identical to base):
    • old assertions, twice: # tests 68 / # pass 68 / # fail 0;
    • new assertions, twice: # tests 72 / # pass 68 / # fail 4, exactly the
      four new tests, including
      + actual: 0 / - expected: 1 for the kept row and
      expected: 'asked for changes' for the stop request.
  3. Builder restored: # tests 72 / # pass 72 / # fail 0, twice; the branch
    carries no throwaway edit. Neighbour suites enqueue-guard (155/155),
    merge-gate (52/52) and review-verdict (11/11) stay green with the
    re-export.

Verify

TZ=UTC npm run verify at this commit: core lint 0 errors, plugin lint 0
errors, 10 patches apply cleanly, core/ equals ds-bot/ + patches/ds-bot/,
canonical no-op; the .github + policy suite is 679 tests / 678 pass / 1 fail — the one red is the known #749 machine item, which names only this
host's .cache/wt-2547/** worktree and not any file of this change;
arch-docs: OK (3 changed file(s)).

No changelog fragment: gate plumbing, nothing a user sees.

Fixes #2870
Owner: Dev-5
Reviewer: Birfy
Written-by: Dev-5
Bot: Dev-5
Claim-Id: 9b6bdf22f96041bb8c08334b5d1f7310
Risk tier: T3 (judge: .github/scripts/enqueue-rules.mjs=T3, .github/scripts/review-gate.mjs=T3, .github/scripts/review-gate.test.mjs=T3)
Base: 0b77add

{
"pr": 2875,
"claim": "Dev-5",
"issue": 2870,
"summary": "review-gate built its reports rows in a third copy that had drifted from the guard and the queue gate: no id, no review state, empty-body reviews dropped, no diff-line comments. reportsFrom now builds all three faces once and the conclusion readers skip the review-comment kind through one predicate. A CHANGES_REQUESTED review with an empty body is now visible as a stop request instead of the report answering PASS. The three builders stay separate; collapsing them is its own change.",
"files": [
".github/scripts/review-gate.mjs",
".github/scripts/enqueue-rules.mjs",
".github/scripts/review-gate.test.mjs"
],
"checks": {
"ran": "TZ=UTC npm run verify; ARCH_DOCS_BASE=0b77addc07 npm --prefix core run arch-docs; review-gate/enqueue-guard/merge-gate/review-verdict suites",
"result": "green",
"at": "763e15078270c128dd5302f76a932c2eecf91e15"
},
"next": "waiting for a PASS at this tip (T3); the three-builder merge stays a separate issue"
}

…ueue read

`.github/scripts/review-gate.mjs` built its `reports` rows in a third copy that
had drifted from `enqueue-guard.mjs` and `merge-gate.mjs`: the review row
carried no `id` (the handle a decision names), no `state` (`stopRequestAt` reads
CHANGES_REQUESTED from it — the whole of a refusal a person writes without
typing), a review whose body was empty was dropped, and a comment written on one
line of the diff never reached the report at all. So this report could say PASS
while the queue gate refused the same tip for a standing request.

`reportsFrom` now builds all three faces once, and the conclusion readers skip
`kind: 'review-comment'` through the one predicate `isConclusionSource`, which
moves to `review-gate.mjs` (the module that owns what a conclusion is) and is
re-exported by `enqueue-rules.mjs`, so both readers keep one definition and no
import cycle is introduced. The three row builders are deliberately left in
three places; merging them is a separate change.
@HugoXK

HugoXK commented Nov 11, 2026

Copy link
Copy Markdown
Contributor Author

@Birfy review request — tip 763e15078270c128dd5302f76a932c2eecf91e15. T3 (three gate files), so this asks for the Verdict at this tip; one request for this tip only.

  • 15 checks at that tip: 11 success + 1 skipped / 3 failure. The three reds are the T3 verdict gate (enqueue-guard: "no Verifier report names the tip 763e15078270"), policy-sign (gate files changed, no signature yet) and tests-ok (collateral — the aggregate job reads SIGN=failure; test is skipped behind it, plugins and package are success).
  • Signing note, so this does not cost a round trip: a signature only has to be a comment written by a non-author type: User account whose text names this tip. A verdict that names the tip is exactly that shape — fix(gate): a review asking for changes stops the queue entry #2120 was signed by the Reviewer's own PASS comment (Policy-sign: 6603688549). Once a verdict names this tip I put Policy-sign: <that comment id> in the body and ask for a full re-run of this run, because a body edit alone does not re-trigger pull_request; then policy-sign and tests-ok go green without moving the tip, so the verdict stays valid.
  • maintainer_can_modify: true; base 0b77addc077c3604e3fd16e2309a25721f3a9ed8; branch dev/5-review-gate-rows; 3 files +112/−12.
  • What changed: review-gate.mjs built its reports rows in a third copy of a shape enqueue-guard.mjs and merge-gate.mjs were already fixed in (Read a stop request written on a review comment line #2092, fix(gate): a review asking for changes stops the queue entry #2120) — no id, no review state, empty-body reviews filtered out, and no inline-comment face. The three faces are now built once, the inline comments arrive as kind: 'review-comment', and conclusions still come only from isConclusionSource.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

gate: review-gate's report rows drop a review's state, id and an empty body

1 participant